import patchVnode from "./patchVnode.js";
import createElement from "./createElement.js";
import patch from "./patch.js";
// 判断是否是同一个虚拟节点
function CheckSameVnode(a, b) {
    return a.sel == b.sel && a.key == b.key;
}
export default function updateChildren(parentElm, oldCh, newCh) {
    let oldStartIdx = 0, //旧前
        newStartIdx = 0, //新前
        newEndIdx = newCh.length - 1, //新后
        oldEndIdx = oldCh.length - 1, //旧后
        oldStartVnode = oldCh[0], //旧前节点
        oldEndVnode = oldCh[oldEndIdx], //旧后节点
        newStartVnode = newCh[0], //新前节点
        newEndVnode = newCh[newEndIdx], //新后节点
        keyMap = null;
    while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
        if (oldStartVnode == null) {
            oldStartVnode = oldCh[++oldStartIdx];
        }
        if (oldEndVnode == null) {
            oldEndVnode = oldCh[--oldEndIdx];
        }
        if (newEndVnode == null) {
            newEndVnode = newCh[--newEndIdx];
        }
        if (newStartVnode == null) {
            newStartVnode = oldCh[++newStartIdx];
        }
        console.log('★');
        // 当前指针在后指针后面的时候，结束循环
        if (CheckSameVnode(oldStartVnode, newStartVnode)) {
            console.log('1命中');
            // 先前节点与旧前节点命中的时候，先前指针与后前指针都要往下移动
            patchVnode(newStartVnode, oldStartVnode);
            oldStartVnode = oldCh[++oldStartIdx];
            newStartVnode = newCh[++newStartIdx];
        } else if (CheckSameVnode(newEndVnode, oldEndVnode)) {
            console.log('2命中');
            // 1未命中，2.比较先后节点与旧后节点
            // 命中就把先后指针和旧后指针往上移
            patchVnode(newEndVnode, oldEndVnode);
            oldEndVnode = oldCh[--oldEndIdx];
            newEndVnode = newCh[--newEndIdx];
        } else if (CheckSameVnode(newEndVnode, oldStartVnode)) {
            console.log('3命中');
            // 1、2都未命中，3.比较先后节点与旧前节点
            // 命中 就把先后指针往上移，旧前指针往下移
            // 命中 就把先前指向的节点移动到旧后节点的后面
            patchVnode(newEndVnode, oldStartVnode);
            parentElm.insertBefore(oldStartVnode.elm, oldEndVnode.elm.nextSibling);
            oldStartVnode = oldCh[++oldStartIdx];
            newEndVnode = newCh[--newEndIdx];
        } else if (CheckSameVnode(newStartVnode, oldEndVnode)) {
            console.log('4命中');
            // 1、2、3都未命中，4.比较先前与旧后节点
            // 命中 就把先前指针往下移，旧后指针往上移
            // 命中 就把旧后指针指向的节点移动到新前指针的前面
            patchVnode(newStartVnode, oldEndVnode);
            parentElm.insertBefore(oldEndVnode.elm, oldStartVnode.elm);
            oldEndVnode = oldCh[--oldEndIdx];
            newStartVnode = newCh[++newStartIdx];
        } else {
            console.log('4中均未命中');
            // 开启暴力循环查找
            // 先用一个表把oldVnode中的各个key对应的位置保存下来
            // 防止寻找的时候反复去遍历查找
            if (!keyMap) {
                keyMap = {};
                for (let i = oldStartIdx; i <= oldEndIdx; i++) {
                    const key = oldCh[i].key;
                    if (key != undefined) {
                        keyMap[key] = i;
                    }
                }
            }
            // 查找新前指针在oldch中对应的位置
            let idxInold = keyMap[newStartVnode.key];
            if (idxInold == undefined) {
                // 表明在oldCh中找不到新前对应的节点，说明这一项需要新创建
                parentElm.insertBefore(createElement(newStartVnode), oldStartVnode.elm);
            } else {

                // 表明在oldCh中找到了新前对应的节点，说明需要移动这个节点的位置
                const elmToMove = oldCh[idxInold];
                // 找到节点，两节点进行对比
                patchVnode(elmToMove, newStartVnode);
                // 移动节点
                oldCh[idxInold] = undefined;
                parentElm.insertBefore(elmToMove.elm, oldStartVnode.elm);
            }

            // 只移动新的指针头
            newStartVnode = newCh[++newStartIdx];
        }

    }
    // 后指针移动到了前指针之前，需要跳出循环
    // 此时我们需要解决删除节点与增加节点的问题
    if (newStartIdx <= newEndIdx) {
        // 这说明是旧后小于旧前导致的循环结束
        // 新前小于新后，说明了还有了剩余的节点没有处理
        // 说明需要插入这些节点
        // const before=newCh[newEndIdx+1]

        // const before = oldCh[oldEndIdx + 1] == null ? null : oldCh[oldEndIdx + 1].elm;
        for (let i = newStartIdx; i <= newEndIdx; i++) {
            parentElm.insertBefore(createElement(newCh[i]), oldCh[oldStartIdx].elm);
            // 插入也需要插入oldVnode
        }
    } else if (oldStartIdx <= oldEndIdx) {
        // 说明要删除多余的oldVnode中的节点
        for (let i = oldStartIdx; i <= oldEndIdx; i++) {
            if (oldCh[i]) {
                parentElm.removeChild(oldCh[i].elm);
                oldCh[i].elm = undefined;
            }
        }
    }

}